package com.sy.simpleegg.ui.fragment

import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import androidx.lifecycle.lifecycleScope
import com.sy.simpleegg.BuildConfig
import com.sy.simpleegg.R
import com.sy.simpleegg.adapter.BackstageAdapter
import com.sy.simpleegg.adapter.LanguageAdapter
import com.sy.simpleegg.adapter.SpinnerAdapter
import com.sy.simpleegg.adapter.SpinnerMotorAdapter
import com.sy.simpleegg.base.BaseMvpFragment
import com.sy.simpleegg.bean.ClearDataBean
import com.sy.simpleegg.config.Config
import com.sy.simpleegg.constant.Constant
import com.sy.simpleegg.constant.Languages
import com.sy.simpleegg.constant.MultPlatform
import com.sy.simpleegg.databinding.FragmentFastManageBinding
import com.sy.simpleegg.event.ClearCoinsEvent
import com.sy.simpleegg.event.RebootControlEvent
import com.sy.simpleegg.event.ResetMotorEvent
import com.sy.simpleegg.event.StartClearCoinsEvent
import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.ext.onClick
import com.sy.simpleegg.ext.setDeviceStatus
import com.sy.simpleegg.ext.showToastMsg
import com.sy.simpleegg.mvp.contract.FastManageContract
import com.sy.simpleegg.mvp.presenter.FastManagePresenter
import com.sy.simpleegg.platform.BackstagePlatform
import com.sy.simpleegg.ui.dialog.ClearCoinDataDialogFragment
import com.sy.simpleegg.util.BoardApiUtil
import com.sy.simpleegg.util.CommonUtil
import com.sy.simpleegg.util.GsonUtil
import com.sy.simpleegg.util.MultiLanguageUtils
import com.sy.simpleegg.util.Preference
import com.sy.simpleegg.util.SPHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

class FastManageFragment :
    BaseMvpFragment<FastManageContract.View, FastManageContract.Presenter, FragmentFastManageBinding>(),
    FastManageContract.View {

    private var outTypes: Array<String>? = null
    private var motorOutType = 0

    private var isClear = false

    private var isReboot = false

    private var rebootJob: Job? = null

    private var clearTimeoutJob: Job? = null

    private var clearDataFragment: ClearCoinDataDialogFragment? = null

    private var lastClickTime: Long = 0L
    private var curClickTime: Long = 0L
    private var clickCount: Int = 1

    companion object {
        fun getInstance(): FastManageFragment = FastManageFragment()
    }

    /**
     * 语言
     */
    private var language: Languages by Preference(Constant.SETTING_LANGUAGE_CONFIG, Languages.ZH)

    /**
     * 设备编号
     */
    private var devNumber: String by Preference(Constant.SETTING_DEVICE_NUMBER, "")
    /**
     * 多平台，主设备编号
     */
    private var mainDevNumber: String by Preference(Constant.SETTING_MAIN_DEVICE_NUMBER, "")

    private var autoCoins: Boolean by Preference(Constant.SETTING_AUTO_COINS, true)

    private var contact: String by Preference(Constant.SETTING_CONTACT, "")
    /**
     * 现金投币按钮显示状态
     */
    private var cashShow: Boolean by Preference(Constant.SETTING_CASH_SHOW, true)
    /**
     * 美团核销按钮显示状态
     */
    private var meituanShow: Boolean by Preference(Constant.SETTING_MEITUAN_SHOW, true)
    /**
     * 抖音核销按钮显示状态
     */
    private var tiktokShow: Boolean by Preference(Constant.SETTING_TIKTOK_SHOW, true)
    /**
     * 会员存币按钮显示状态
     */
    private var saveShow: Boolean by Preference(Constant.SETTING_SAVE_SHOW, true)
    /**
     * 核销按钮显示状态
     */
    private var writeOffShow: Boolean by Preference(Constant.SETTING_WRITE_OFF_SHOW, true)
    /**
     * 提币按钮显示状态
     */
    private var withdrawalShow: Boolean by Preference(Constant.SETTING_WITHDRAWAL_SHOW, true)

    /**
     * 接入第三方平台
     */
    private var platform: BackstagePlatform by Preference(Constant.SETTING_OTHER_PLATFORM, BackstagePlatform.WHM_MQTT_HEX)
    /**
     * lyybox通讯
     */
    private var lyyboxOpen: Boolean by Preference(
        Constant.SETTING_LYYBOX_OPEN,
        BuildConfig.LYYBOX_OPEN
    )
    /**
     * 国家地区
     */
    private var country: Int by Preference(Constant.SETTING_COUNTRY, Config.DEFAULT_COUNTRY_CODE)

    /**
     * KKB商户识别码
     */
    private var kkbIdentity: String by Preference(Constant.SETTING_KKB_IDENTITY, "")

    /**
     * 开启多平台
     */
    private var openMultPlatform: MultPlatform by Preference(Constant.SETTING_OPEN_MULT_PLATFORM, MultPlatform.OPEN)

    /**
     * 订单自动补币
     * 开启后设备出币异常时会停止设备运行，并在启动时自动处理未出币订单
     * 关闭后设备出币异常后可以继续正常运行，出币异常订单会记录在后台页面，可以手动选择订单补币
     */
    private var orderSupplement: Boolean by Preference(Constant.SETTING_ORDER_SUPPLEMENT, false)

    private var controlType = 0
    private var goodType = 3


    override fun createPresenter(): FastManageContract.Presenter =
        FastManagePresenter(lifecycleScope)

    override fun attachLayoutRes(): Int = R.layout.fragment_fast_manage

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        openEventBus = true
        isCountDownBackHome = false
    }

    override fun initView(view: View) {
        super.initView(view)

        binding.tvDevNumber.text = if (mainDevNumber.isEmpty()) "" else "main:${mainDevNumber}\nsub:" + devNumber

        binding.tvIccid.text = BoardApiUtil.getIccid()

        binding.tvPlatform.onClick(0L) {
            showMultPlatformSwitch()
        }
        binding.switchMultPlatform.isChecked = when (openMultPlatform){
            MultPlatform.OPEN -> true
            MultPlatform.CLOSE -> false
        }
        binding.switchMultPlatform.setOnCheckedChangeListener { buttonView, isChecked ->
            openMultPlatform = if (isChecked) MultPlatform.OPEN else MultPlatform.CLOSE
            showToastMsg(getString(R.string.switch_good_type_tips))
        }
        binding.llMultPlatform.visibility = View.GONE

        binding.cbDeviceAutoCoin.isChecked = autoCoins
        binding.cbDeviceAutoCoin.setOnCheckedChangeListener { buttonView, isChecked ->
            autoCoins = isChecked
            showToastMsg("自动补币${if (isChecked) "开启" else "关闭"}")
        }

        binding.cbOrderSupplement.isChecked = orderSupplement
        binding.cbOrderSupplement.setOnCheckedChangeListener { buttonView, isChecked ->
            orderSupplement = isChecked
            showToastMsg("订单补币${if (isChecked) "开启" else "关闭"}")
        }

        binding.btnDeviceInCoin.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            inCoins()
        }

        binding.btnRebootControl.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            rebootControl()
        }

        binding.btnDeviceClearCoin.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            startClearCoins()
        }

        binding.btnMotorState.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            clearMotorState()
        }

        binding.btnDeviceClearCoinData.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            getClearData()
        }

        binding.btnDeviceClearRemainMoney.setOnClickListener {
            if (!isFirstClick()){
                return@setOnClickListener
            }
            SPHelper.setDeviceRemainCash(0)
            binding.tvDeviceMoneyRemain.text = "0"
        }

        outTypes = arrayOf(
            getString(R.string.out_type_motor_1),
            getString(R.string.out_type_motor_2),
            getString(R.string.out_type_Alternately) //                , getString(R.string.out_type_Asynchronization)
        )
        binding.spOutType.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long,
            ) {
                if (position == motorOutType) {
                    return
                }
                SPHelper.setMotorType(position)
                motorOutType = position
                showToastMsg("设置完成")
                setMotorState()
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }
        binding.spOutType.adapter = SpinnerMotorAdapter(outTypes!!)
        motorOutType = SPHelper.getMotorType()
        binding.spOutType.setSelection(motorOutType)

        setMotorState()

        val backstageList: MutableList<String> = mutableListOf()
        BackstagePlatform.entries.forEach { backstage ->
            backstageList.add("${backstage.backstageCode},${backstage.backstageName}")
        }
        binding.spBackstageType.onItemSelectedListener = object : OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val selectBackstage = backstageList[position]
                val code = selectBackstage.split(",")[0].toInt()
                if (platform.backstageCode == code){
                    return
                }
                platform = CommonUtil.getBackstage(code)
                when (platform){
                    BackstagePlatform.DEF_MQTT -> {
                        kkbIdentityShow(false)
                    }
                    BackstagePlatform.LYY_SDK -> {
                        lyyboxOpen = true
                        kkbIdentityShow(false)
                    }
                    BackstagePlatform.LYY_BOX -> {
                        lyyboxOpen = true
                        kkbIdentityShow(false)
                    }
                    BackstagePlatform.WHM_MQTT -> {
                        lyyboxOpen = false
                        kkbIdentityShow(false)
                    }
                    BackstagePlatform.WHM_MQTT_HEX -> {
                        lyyboxOpen = false
                        kkbIdentityShow(false)
                    }

                    BackstagePlatform.YCH_SDK -> {
                        lyyboxOpen = false
                        kkbIdentityShow(false)
                    }

                    BackstagePlatform.KKB -> {
                        lyyboxOpen = false
                        kkbIdentityShow(true)
                    }
                }
                showToastMsg(getString(R.string.switch_backstage_tips))
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }
        binding.spBackstageType.adapter = BackstageAdapter(backstageList)
        backstageList.forEachIndexed { index, backstage ->
            if (backstage.split(",")[0].toInt() == platform.backstageCode){
                binding.spBackstageType.setSelection(index)
            }
        }

        val controlBoardList = arrayOf(getString(R.string.control_type_lyy), getString(R.string.control_type_fix))
        binding.spControlType.onItemSelectedListener = object : OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long,
            ) {
                if (position == controlType) {
                    return
                }
                SPHelper.setControlType(position)
                logFile("选中控制板类型：${controlBoardList[position]}")
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }
        binding.spControlType.adapter = SpinnerAdapter(controlBoardList)
        controlType = SPHelper.getControlType()
        binding.spControlType.setSelection(controlType)

        val languageList: MutableList<String> = mutableListOf()
        Languages.entries.forEach { l ->
            languageList.add("${l.lan},${l.area},${l.alia},${l.lanCode}")
        }
        binding.spLanguage.onItemSelectedListener = object : OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                val selectLanguage = languageList[position]
                val lan = selectLanguage.split(",")[0]
                val area = selectLanguage.split(",")[1]
                val currentLan = language.lan
                val currentArea = language.area
                if (lan == currentLan && area == currentArea){
                    return
                }
                Languages.entries.forEach { lanItem ->
                    if (lanItem.lan == lan && lanItem.area == area){
                        language = lanItem
                        country = lanItem.lanCode
                        MultiLanguageUtils.changeLanguage(requireContext(), lan, "r$area")
                        showToastMsg(getString(R.string.switch_language_tips))
                    }
                }
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }
        binding.spLanguage.adapter = LanguageAdapter(languageList)
        languageList.forEachIndexed { index, lanItem ->
            val lan = lanItem.split(",")[0]
            val area = lanItem.split(",")[1]
            val currentLan = language.lan
            val currentArea = language.area
            if (lan == currentLan && area ==currentArea){
                binding.spLanguage.setSelection(index)
            }
        }

        val goodTypes = arrayOf(getString(R.string.currency), getString(R.string.bead))
        binding.spGoodType.onItemSelectedListener = object : OnItemSelectedListener{
            override fun onItemSelected(
                parent: AdapterView<*>?,
                view: View?,
                position: Int,
                id: Long
            ) {
                if (position == SPHelper.getGoodType() - 3){
                    return
                }
                SPHelper.setGoodType(position + 3)
                goodType = position + 3
                showToastMsg(getString(R.string.switch_good_type_tips))
            }

            override fun onNothingSelected(parent: AdapterView<*>?) {

            }
        }
        binding.spGoodType.adapter = SpinnerAdapter(goodTypes)
        goodType = SPHelper.getGoodType()
        binding.spGoodType.setSelection(goodType - 3)



        binding.switchCash.isChecked = cashShow
        binding.switchMeituan.isChecked = meituanShow
        binding.switchTiktok.isChecked = tiktokShow
        binding.switchSaveCoin.isChecked = saveShow
        binding.switchWithdrawal.isChecked = withdrawalShow
        binding.switchWriteOff.isChecked = writeOffShow
        binding.switchCash.setOnCheckedChangeListener { buttonView, isChecked ->
            cashShow = isChecked
        }
        binding.switchMeituan.setOnCheckedChangeListener { buttonView, isChecked ->
            meituanShow = isChecked
        }
        binding.switchTiktok.setOnCheckedChangeListener { buttonView, isChecked ->
            tiktokShow = isChecked
        }
        binding.switchSaveCoin.setOnCheckedChangeListener { buttonView, isChecked ->
            saveShow = isChecked
        }
        binding.switchWithdrawal.setOnCheckedChangeListener { buttonView, isChecked ->
            withdrawalShow = isChecked
        }
        binding.switchWriteOff.setOnCheckedChangeListener { buttonView, isChecked ->
            writeOffShow = isChecked
        }

        binding.etContact.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(
                s: CharSequence?,
                start: Int,
                count: Int,
                after: Int
            ) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                logFile("onTextChanged s=$s start=$start before=$before count=$count")
                s?.let {
                    contact = it.toString()
                }
            }

            override fun afterTextChanged(s: Editable?) {

            }
        })

        binding.etIdentity.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(
                s: CharSequence?,
                start: Int,
                count: Int,
                after: Int
            ) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                logFile("onTextChanged s=$s start=$start before=$before count=$count")
                s?.let {
                    kkbIdentity = it.toString()
                }
            }

            override fun afterTextChanged(s: Editable?) {

            }
        })

        when (platform){
            BackstagePlatform.DEF_MQTT -> {
                kkbIdentityShow(false)
            }
            BackstagePlatform.LYY_SDK -> {
                lyyboxOpen = true
                kkbIdentityShow(false)
            }
            BackstagePlatform.LYY_BOX -> {
                lyyboxOpen = true
                kkbIdentityShow(false)
            }
            BackstagePlatform.WHM_MQTT -> {
                lyyboxOpen = false
                kkbIdentityShow(false)
            }
            BackstagePlatform.WHM_MQTT_HEX -> {
                lyyboxOpen = false
                kkbIdentityShow(false)
            }

            BackstagePlatform.YCH_SDK -> {
                lyyboxOpen = false
                kkbIdentityShow(false)
            }

            BackstagePlatform.KKB -> {
                lyyboxOpen = false
                kkbIdentityShow(true)
            }
        }

        isClear = false

//        binding.rlTouch.setTouchListener(object : TouchRelativeLayout.TouchListener {
//            override fun touch() {
//                startCountDown()
//            }
//        })
    }

    override fun getViewBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
    ): FragmentFastManageBinding {
        return FragmentFastManageBinding.inflate(inflater, container, false)
    }

    override fun lazyLoad() {

    }

    override fun onResume() {
        super.onResume()
        logFile("${javaClass.simpleName} onResume")
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (hidden) {
            logFile("${javaClass.simpleName}隐藏")
        } else {
            logFile("${javaClass.simpleName}显示")
        }
    }

    override fun saveCoinsFinish() {
        showToastMsg("补币完成")
    }

    override fun showClearData(clearDatas: MutableList<ClearDataBean>?) {
        if (clearDatas.isNullOrEmpty()){
            showToastMsg("清币数据为空")
            return
        }
        showClearDataDialog(clearDatas)
    }

    override fun showLoading() {

    }

    override fun hideLoading() {

    }

    override fun onDetach() {
        super.onDetach()
        rebootJob?.cancel()
    }

    /**
     * 补币
     */
    private fun inCoins() {
        try {
            val inCoins = binding.etInCoin.text.toString()
            if (inCoins.isEmpty()) {
                showToastMsg(getString(R.string.input_tips))
                return
            }
            val coins = inCoins.toLong()
            if (coins in 1..99998) {
                mPresenter?.saveCoins(coins)
            } else {
                showToastMsg(getString(R.string.input_tips))
            }
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("补币异常：${e.message}")
        }
    }

    /**
     * 更新马达状态
     */
    private fun setMotorState() {
        val m1s = SPHelper.getMotor1()
        val m2s = SPHelper.getMotor2()
        var msg = ""
        when (motorOutType) {
            Constant.MOTOR_TYPE_SINGLE_1 -> msg = if (m1s) requireContext().getString(R.string.motor1_normal) else requireContext().getString(R.string.motor1_error)
            Constant.MOTOR_TYPE_SINGLE_2 -> msg = if (m2s) requireContext().getString(R.string.motor2_normal) else requireContext().getString(R.string.motor2_error)
            Constant.MOTOR_TYPE_ALTERNATELY, Constant.MOTOR_TYPE_ASYNCHRONIZATION -> {
                val m1Str = if (m1s) requireContext().getString(R.string.motor1_normal) else requireContext().getString(R.string.motor1_error)
                val m2Str = if (m2s) requireContext().getString(R.string.motor2_normal) else requireContext().getString(R.string.motor2_error)
                msg = """
                $m1Str
                $m2Str
                """.trimIndent()
            }

            else -> {}
        }
        binding.tvMotorState.text = msg
    }

    /**
     * 重启控制板
     */
    private fun rebootControl(){
        try {
            if (isReboot) {
                showToastMsg("控制板重启中，请稍等")
                return
            }
            isReboot = true
            EventBus.getDefault().post(RebootControlEvent(0))
            rebootJob?.cancel()
            rebootJob = lifecycleScope.launch(Dispatchers.IO) {
                delay(10000)
                isReboot = false
            }
        }catch (e: Exception){
            e.printStackTrace()
            logFile("重启控制板处理异常：${e.message}")
        }
    }

    /**
     * 清币
     */
    private fun startClearCoins(){
        try {
            if (isClear){
                showToastMsg("清币中，请稍等")
                return
            }
            isClear = true
            EventBus.getDefault().post(StartClearCoinsEvent(""))
            clearTimeout()
        }catch (e: Exception){
            e.printStackTrace()
            logFile("发送按钮处理异常：${e.message}")
        }
    }

    private fun clearTimeout(){
        clearTimeoutJob?.cancel()
        clearTimeoutJob = lifecycleScope.launch(Dispatchers.IO) {
            delay(20000)
            isClear = false
        }
    }

    private fun cancelClearTimeout(){
        clearTimeoutJob?.cancel()
        isClear = false
    }

    /**
     * 清除马达状态
     */
    private fun clearMotorState(){
        lifecycleScope.launch {
            setDeviceStatus(true)
            SPHelper.setMotor1(true)
            SPHelper.setMotor2(true)
            delay(1000)
            setMotorState()
            EventBus.getDefault().post(ResetMotorEvent())
        }
    }

    /**
     * 显示清币数据
     */
    private fun getClearData(){
        if (isClear){
            showToastMsg("清币中")
            return
        }
        mPresenter?.getClearData()
    }

    /**
     * 显示清币数据
     * @param clearDatas 数据
     */
    private fun showClearDataDialog(clearDatas: MutableList<ClearDataBean>){
        try {
            if (clearDataFragment != null) {
                clearDataFragment?.dismissAllowingStateLoss()
            }
            clearDataFragment = ClearCoinDataDialogFragment(clearDatas)
            clearDataFragment?.show(childFragmentManager, "ClearCoinDataDialogFragment")
        }catch (e: Exception){
            e.printStackTrace()
            logFile("打开清币数据窗口异常：${e.message}")
        }
    }

    private fun kkbIdentityShow(show: Boolean){
        binding.llIdentity.visibility = if (show) {
            binding.etIdentity.setText(kkbIdentity)
            View.VISIBLE
        } else View.GONE
    }

    private fun showMultPlatformSwitch() {
        lastClickTime = curClickTime
        curClickTime = System.currentTimeMillis()
        if (curClickTime - lastClickTime < 500) {
            clickCount++
            if (clickCount == Constant.KEYBOARD_CLICK_COUNT) {
                clickCount = 1
                binding.llMultPlatform.visibility = View.VISIBLE
            }else if(clickCount > Constant.KEYBOARD_CLICK_COUNT){
                clickCount = 1
            }
        } else {
            clickCount = 1
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun clearCoinsEvent(event: ClearCoinsEvent) {
        try {
            logFile("刷新清币数量事件：${GsonUtil.getInstance()?.toJson(event)}")
            binding.tvClearCoin.text = event.coins
            if (event.finish){
                cancelClearTimeout()
            }
        } catch (e: Exception) {
            e.printStackTrace()
            logFile("刷新清币数量事件处理异常：${e.message}")
        }
    }
}